En este proyecto, nos enfocaremos en la cadena de suministro utilizando un dataset extenso que abarca información de ventas y operaciones. El objetivo es explorar, limpiar y analizar los datos para obtener insights valiosos que puedan ayudar a mejorar la eficiencia y efectividad en la gestión de la cadena de suministro.
En la primera fase del análisis de datos, nos enfocamos en la Exploración Inicial para obtener una visión general del dataset. Esta etapa es fundamental para entender la estructura del conjunto de datos, identificando las características principales, el tipo de datos en cada columna, y revisando una muestra de los registros. Al realizar esta exploración, se busca confirmar que los datos se han cargado correctamente y que las columnas están en el formato adecuado para un análisis más detallado.
La Limpieza de Datos, por otro lado, es crucial para preparar el dataset para el análisis. En esta fase, se abordan problemas como la presencia de valores faltantes, duplicados y errores en los datos. Se identifican y eliminan columnas irrelevantes, se corrigen o imputan valores nulos, y se transforman datos para que sean consistentes y útiles. Esta limpieza asegura que el dataset sea preciso y esté libre de inconsistencias, facilitando así análisis posteriores más robustos y confiables.
Importamos las librerías y herramientas necesarias para el desarrollo del proyecto. Éstas incluyen:
import numpy as np
import pandas as pd
import seaborn as sns; sns.set(style="ticks", color_codes=True)
import matplotlib.pyplot as plt
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import seaborn as sns
import plotly.express as px
%matplotlib inline
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected = False)
Cargar el conjunto de datos en el entorno de trabajo
Realizar una revisión general
dataset original
#Importación de dataset desde github
url = 'https://github.com/ISPC-PP1-2024/proyecto/blob/main/datos/DataCoSupplyChainDataset/DataCoSupplyChainDataset.csv'
df_1 = pd.read_csv(url)
# dataset original -para jupyter
df_1=pd.read_csv('C:\\Users\\Usuario\\Desktop\\2024\\materias\\CDIA\\2semestre\\pp1-cdia23\\ejemplo suply chain\\DataCoSupplyChainDataset.csv\\para jupyter\\SinAcento.csv', encoding='latin1', sep=';', low_memory=False)
pd.set_option('display.max_rows', 60) #muestra 60 columnas
pd.set_option('display.max_columns', 100) # 100 filas
pd.set_option('display.width', 1000)
# detalle
df_1.head()
| Type | Days for shipping (real) | Days for shipment (scheduled) | Benefit per order | Sales per customer | Delivery Status | Late_delivery_risk | Category Id | Category Name | Customer City | Customer Country | Customer Email | Customer Fname | Customer Id | Customer Lname | Customer Password | Customer Segment | Customer State | Customer Street | Customer Zipcode | Department Id | Department Name | Latitude | Longitude | Market | Order City | Order Country | Order Customer Id | order date (DateOrders) | Order Id | Order Item Cardprod Id | Order Item Discount | Order Item Discount Rate | Order Item Id | Order Item Product Price | Order Item Profit Ratio | Order Item Quantity | Sales | Order Item Total | Order Profit Per Order | Order Region | Order State | Order Status | Order Zipcode | Product Card Id | Product Category Id | Product Description | Product Image | Product Name | Product Price | Product Status | shipping date (DateOrders) | Shipping Mode | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | DEBIT | 3 | 4 | 9.125000e+01 | 3.146400e+09 | Advance shipping | 0 | 73 | Sporting Goods | Caguas | Puerto Rico | XXXXXXXXX | Cally | 20755 | Holloway | XXXXXXXXX | Consumer | PR | 5365 Noble Nectar Island | 725.0 | 2 | Fitness | 182.514.534 | -6.603.705.597 | Pacific Asia | Bekasi | Indonesia | 20755 | 1/31/2018 22:56 | 77202 | 1360 | 1.310.999.966 | 0.04 | 180517 | 327.75 | 0.289999992 | 1 | 327.75 | 3.146.400.146 | 91.25 | Southeast Asia | Java Occidental | COMPLETE | NaN | 1360 | 73 | NaN | http://images.acmesports.sports/Smart+watch | Smart watch | 327.75 | 0 | 2/3/2018 22:56 | Standard Class |
| 1 | TRANSFER | 5 | 4 | -2.490900e+09 | 3.113600e+09 | Late delivery | 1 | 73 | Sporting Goods | Caguas | Puerto Rico | XXXXXXXXX | Irene | 19492 | Luna | XXXXXXXXX | Consumer | PR | 2679 Rustic Loop | 725.0 | 2 | Fitness | 1.827.945.137 | -660.370.636 | Pacific Asia | Bikaner | India | 19492 | 1/13/2018 12:27 | 75939 | 1360 | 1.638.999.939 | 0.05 | 179254 | 327.75 | -0.800000012 | 1 | 327.75 | 3.113.599.854 | -2.490.899.963 | South Asia | Rajastán | PENDING | NaN | 1360 | 73 | NaN | http://images.acmesports.sports/Smart+watch | Smart watch | 327.75 | 0 | 1/18/2018 12:27 | Standard Class |
| 2 | CASH | 4 | 4 | -2.477800e+09 | 3.097200e+09 | Shipping on time | 0 | 73 | Sporting Goods | San Jose | EE. UU. | XXXXXXXXX | Gillian | 19491 | Maldonado | XXXXXXXXX | Consumer | CA | 8510 Round Bear Gate | 95125.0 | 2 | Fitness | 3.729.223.251 | -121.881.279 | Pacific Asia | Bikaner | India | 19491 | 1/13/2018 12:06 | 75938 | 1360 | 1.803.000.069 | 0.06 | 179253 | 327.75 | -0.800000012 | 1 | 327.75 | 3.097.200.012 | -2.477.799.988 | South Asia | Rajastán | CLOSED | NaN | 1360 | 73 | NaN | http://images.acmesports.sports/Smart+watch | Smart watch | 327.75 | 0 | 1/17/2018 12:06 | Standard Class |
| 3 | DEBIT | 3 | 4 | 2.286000e+09 | 3.048100e+09 | Advance shipping | 0 | 73 | Sporting Goods | Los Angeles | EE. UU. | XXXXXXXXX | Tana | 19490 | Tate | XXXXXXXXX | Home Office | CA | 3200 Amber Bend | 90027.0 | 2 | Fitness | 3.412.594.605 | -1.182.910.156 | Pacific Asia | Townsville | Australia | 19490 | 1/13/2018 11:45 | 75937 | 1360 | 2.294.000.053 | 0.07 | 179252 | 327.75 | 0.079999998 | 1 | 327.75 | 3.048.099.976 | 2.286.000.061 | Oceania | Queensland | COMPLETE | NaN | 1360 | 73 | NaN | http://images.acmesports.sports/Smart+watch | Smart watch | 327.75 | 0 | 1/16/2018 11:45 | Standard Class |
| 4 | PAYMENT | 2 | 4 | 1.342100e+09 | 2.982500e+02 | Advance shipping | 0 | 73 | Sporting Goods | Caguas | Puerto Rico | XXXXXXXXX | Orli | 19489 | Hendricks | XXXXXXXXX | Corporate | PR | 8671 Iron Anchor Corners | 725.0 | 2 | Fitness | 1.825.376.892 | -6.603.704.834 | Pacific Asia | Townsville | Australia | 19489 | 1/13/2018 11:24 | 75936 | 1360 | 29.5 | 0.09 | 179251 | 327.75 | 0.449999988 | 1 | 327.75 | 298.25 | 1.342.100.067 | Oceania | Queensland | PENDING_PAYMENT | NaN | 1360 | 73 | NaN | http://images.acmesports.sports/Smart+watch | Smart watch | 327.75 | 0 | 1/15/2018 11:24 | Standard Class |
# tamaño en filas y columnas del dataset original
df_1.shape
(180519, 53)
# trabajo previo
# 1- filtrar el set de datos original por pais para abarcar solo argentina, brasil y mexico
# 2- quitar columnas
#EL DATAFRAME RESULTANTE DE ESTE PROCESO SE EMPLEA PARA TRABAJAR
Operaciones sobr el conjunto de datos
Se realiza un filtrado sobre el dataset original para incluir solo los paises: Argentina, Brasil y Mexico
df = df_1[df_1['Order Country'].isin(['Argentina', 'Brasil', 'Mexico'])]
#Mostrar los primeras filas del dataframe resultante
df.head()
| Type | Days for shipping (real) | Days for shipment (scheduled) | Benefit per order | Sales per customer | Delivery Status | Late_delivery_risk | Category Id | Category Name | Customer City | Customer Country | Customer Email | Customer Fname | Customer Id | Customer Lname | Customer Password | Customer Segment | Customer State | Customer Street | Customer Zipcode | Department Id | Department Name | Latitude | Longitude | Market | Order City | Order Country | Order Customer Id | order date (DateOrders) | Order Id | Order Item Cardprod Id | Order Item Discount | Order Item Discount Rate | Order Item Id | Order Item Product Price | Order Item Profit Ratio | Order Item Quantity | Sales | Order Item Total | Order Profit Per Order | Order Region | Order State | Order Status | Order Zipcode | Product Card Id | Product Category Id | Product Description | Product Image | Product Name | Product Price | Product Status | shipping date (DateOrders) | Shipping Mode | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 84 | PAYMENT | 4 | 2 | 2.347000e+09 | 144.0 | Late delivery | 1 | 24 | Women's Apparel | Caguas | Puerto Rico | XXXXXXXXX | Mary | 8541 | Smith | XXXXXXXXX | Home Office | PR | 5700 Little Circle | 725.0 | 5 | Golf | 1.829.609.299 | -6.637.050.629 | LATAM | Juazeiro | Brasil | 8541 | 4/11/2017 15:49 | 56973 | 502 | 6 | 0.04 | 142502 | 50 | 0.159999996 | 3 | 150 | 144 | 2.346.999.931 | South America | Bahía | PENDING_PAYMENT | NaN | 502 | 24 | NaN | http://images.acmesports.sports/Nike+Men%27s+D... | Nike Men's Dri-FIT Victory Golf Polo | 50 | 0 | 4/15/2017 15:49 | Second Class |
| 86 | PAYMENT | 6 | 2 | 4.366000e+09 | 139.5 | Late delivery | 1 | 24 | Women's Apparel | Caguas | Puerto Rico | XXXXXXXXX | Mary | 3752 | Vega | XXXXXXXXX | Home Office | PR | 7840 Umber Sky Villas | 725.0 | 5 | Golf | 182.105.732 | -6.637.058.258 | LATAM | Mexico City | Mexico | 3752 | 3/16/2017 2:54 | 55155 | 502 | 10.5 | 0.07 | 137932 | 50 | 0.310000002 | 3 | 150 | 139.5 | 4.365.999.985 | Central America | Distrito Federal | PENDING_PAYMENT | NaN | 502 | 24 | NaN | http://images.acmesports.sports/Nike+Men%27s+D... | Nike Men's Dri-FIT Victory Golf Polo | 50 | 0 | 3/22/2017 2:54 | Second Class |
| 87 | PAYMENT | 2 | 2 | 1.320000e+09 | 132.0 | Shipping on time | 0 | 24 | Women's Apparel | Caguas | Puerto Rico | XXXXXXXXX | Wayne | 4673 | Hodges | XXXXXXXXX | Home Office | PR | 7509 Iron Concession | 725.0 | 5 | Golf | 1.820.111.656 | -6.637.059.021 | LATAM | Tlaquepaque | Mexico | 4673 | 3/29/2015 10:33 | 5991 | 502 | 18 | 0.12 | 14921 | 50 | 0.100000001 | 3 | 150 | 132 | 1.319.999.981 | Central America | Jalisco | PENDING_PAYMENT | NaN | 502 | 24 | NaN | http://images.acmesports.sports/Nike+Men%27s+D... | Nike Men's Dri-FIT Victory Golf Polo | 50 | 0 | 3/31/2015 10:33 | Second Class |
| 88 | PAYMENT | 4 | 2 | 4.620000e+09 | 132.0 | Late delivery | 1 | 24 | Women's Apparel | Caguas | Puerto Rico | XXXXXXXXX | Mary | 5367 | Mccormick | XXXXXXXXX | Home Office | PR | 2199 Silver Autumn Key | 725.0 | 5 | Golf | 1.821.469.116 | -6.637.051.392 | LATAM | Puebla | Mexico | 5367 | 2/3/2015 00:28 | 2263 | 502 | 18 | 0.12 | 5671 | 50 | 0.349999994 | 3 | 150 | 132 | 4.620.000.076 | Central America | Puebla | PENDING_PAYMENT | NaN | 502 | 24 | NaN | http://images.acmesports.sports/Nike+Men%27s+D... | Nike Men's Dri-FIT Victory Golf Polo | 50 | 0 | 2/7/2015 00:28 | Second Class |
| 89 | PAYMENT | 4 | 2 | 1.044000e+09 | 130.5 | Late delivery | 1 | 24 | Women's Apparel | Caguas | Puerto Rico | XXXXXXXXX | Mary | 5367 | Mccormick | XXXXXXXXX | Home Office | PR | 2199 Silver Autumn Key | 725.0 | 5 | Golf | 1.821.469.116 | -6.637.051.392 | LATAM | Puebla | Mexico | 5367 | 2/3/2015 00:28 | 2263 | 502 | 19.5 | 0.13 | 5669 | 50 | 0.079999998 | 3 | 150 | 130.5 | 1.043.999.958 | Central America | Puebla | PENDING_PAYMENT | NaN | 502 | 24 | NaN | http://images.acmesports.sports/Nike+Men%27s+D... | Nike Men's Dri-FIT Victory Golf Polo | 50 | 0 | 2/7/2015 00:28 | Second Class |
#Mostrar las ultimas filas del dataframe resultante
df.tail()
| Type | Days for shipping (real) | Days for shipment (scheduled) | Benefit per order | Sales per customer | Delivery Status | Late_delivery_risk | Category Id | Category Name | Customer City | Customer Country | Customer Email | Customer Fname | Customer Id | Customer Lname | Customer Password | Customer Segment | Customer State | Customer Street | Customer Zipcode | Department Id | Department Name | Latitude | Longitude | Market | Order City | Order Country | Order Customer Id | order date (DateOrders) | Order Id | Order Item Cardprod Id | Order Item Discount | Order Item Discount Rate | Order Item Id | Order Item Product Price | Order Item Profit Ratio | Order Item Quantity | Sales | Order Item Total | Order Profit Per Order | Order Region | Order State | Order Status | Order Zipcode | Product Card Id | Product Category Id | Product Description | Product Image | Product Name | Product Price | Product Status | shipping date (DateOrders) | Shipping Mode | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 179618 | TRANSFER | 6 | 4 | 1.337500e+02 | 2.729500e+09 | Late delivery | 1 | 17 | Cleats | Caguas | Puerto Rico | XXXXXXXXX | Brenda | 12354 | Wells | XXXXXXXXX | Consumer | PR | 3762 Amber Estates | 725.0 | 4 | Apparel | 1.823.072.052 | -6.637.063.599 | LATAM | Goiânia | Brasil | 12354 | 4/18/2015 13:41 | 7370 | 365 | 27 | 0.09 | 18457 | 5.999.000.168 | 0.49000001 | 5 | 2.999.500.122 | 2.729.500.122 | 133.75 | South America | Goiás | PENDING | NaN | 365 | 17 | NaN | http://images.acmesports.sports/Perfect+Fitnes... | Perfect Fitness Perfect Rip Deck | 5.999.000.168 | 0 | 4/24/2015 13:41 | Standard Class |
| 179621 | TRANSFER | 3 | 4 | -2.610000e+09 | 2.609600e+09 | Advance shipping | 0 | 17 | Cleats | Juana Diaz | Puerto Rico | XXXXXXXXX | Mary | 10344 | Smith | XXXXXXXXX | Consumer | PR | 2839 Grand Timber Canyon | 795.0 | 4 | Apparel | 1.805.199.051 | -6.650.184.631 | LATAM | Villahermosa | Mexico | 10344 | 5/16/2017 21:33 | 59387 | 365 | 3.899.000.168 | 0.13 | 148676 | 5.999.000.168 | -0.100000001 | 5 | 2.999.500.122 | 2.609.599.915 | -2.610.000.038 | Central America | Tabasco | PENDING | NaN | 365 | 17 | NaN | http://images.acmesports.sports/Perfect+Fitnes... | Perfect Fitness Perfect Rip Deck | 5.999.000.168 | 0 | 5/19/2017 21:33 | Standard Class |
| 179623 | TRANSFER | 2 | 4 | 1.174300e+09 | 2.609600e+09 | Advance shipping | 0 | 17 | Cleats | Caguas | Puerto Rico | XXXXXXXXX | Mary | 8917 | Smith | XXXXXXXXX | Consumer | PR | 4992 Jagged Forest Subdivision | 725.0 | 4 | Apparel | 1.822.487.068 | -6.637.052.155 | LATAM | Barueri | Brasil | 8917 | 4/13/2017 14:25 | 57106 | 365 | 3.899.000.168 | 0.13 | 142839 | 5.999.000.168 | 0.449999988 | 5 | 2.999.500.122 | 2.609.599.915 | 1.174.300.003 | South America | São Paulo | PENDING | NaN | 365 | 17 | NaN | http://images.acmesports.sports/Perfect+Fitnes... | Perfect Fitness Perfect Rip Deck | 5.999.000.168 | 0 | 4/15/2017 14:25 | Standard Class |
| 179624 | TRANSFER | 3 | 4 | 4.844000e+09 | 2.549600e+09 | Advance shipping | 0 | 17 | Cleats | Caguas | Puerto Rico | XXXXXXXXX | Mary | 9204 | Harris | XXXXXXXXX | Consumer | PR | 8713 Quaking Abbey | 725.0 | 4 | Apparel | 1.828.453.636 | -6.637.060.547 | LATAM | Maceió | Brasil | 9204 | 5/27/2017 16:48 | 60127 | 365 | 4.499.000.168 | 0.15 | 150462 | 5.999.000.168 | 0.189999998 | 5 | 2.999.500.122 | 2.549.600.067 | 4.843.999.863 | South America | Alagoas | PENDING | NaN | 365 | 17 | NaN | http://images.acmesports.sports/Perfect+Fitnes... | Perfect Fitness Perfect Rip Deck | 5.999.000.168 | 0 | 5/30/2017 16:48 | Standard Class |
| 179628 | TRANSFER | 3 | 4 | 6.749000e+09 | 2.249600e+09 | Advance shipping | 0 | 17 | Cleats | Caguas | Puerto Rico | XXXXXXXXX | Jerry | 7024 | Smith | XXXXXXXXX | Consumer | PR | 5149 Rocky Pine Moor | 725.0 | 4 | Apparel | 1.822.907.066 | -6.637.058.258 | LATAM | Mexico City | Mexico | 7024 | 5/19/2017 3:51 | 59542 | 365 | 7.498.999.786 | 0.25 | 149029 | 5.999.000.168 | 0.300000012 | 5 | 2.999.500.122 | 2.249.600.067 | 6.748.999.786 | Central America | Distrito Federal | PENDING | NaN | 365 | 17 | NaN | http://images.acmesports.sports/Perfect+Fitnes... | Perfect Fitness Perfect Rip Deck | 5.999.000.168 | 0 | 5/22/2017 3:51 | Standard Class |
#Nuevo tamaño del dataframe
df.shape
(23090, 53)
Información general del DataFrame ---tipo de datos---
df.info()
<class 'pandas.core.frame.DataFrame'> Index: 23090 entries, 84 to 179628 Data columns (total 53 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Type 23090 non-null object 1 Days for shipping (real) 23090 non-null int64 2 Days for shipment (scheduled) 23090 non-null int64 3 Benefit per order 23090 non-null float64 4 Sales per customer 23090 non-null float64 5 Delivery Status 23090 non-null object 6 Late_delivery_risk 23090 non-null int64 7 Category Id 23090 non-null int64 8 Category Name 23090 non-null object 9 Customer City 23090 non-null object 10 Customer Country 23090 non-null object 11 Customer Email 23090 non-null object 12 Customer Fname 23090 non-null object 13 Customer Id 23090 non-null int64 14 Customer Lname 23090 non-null object 15 Customer Password 23090 non-null object 16 Customer Segment 23090 non-null object 17 Customer State 23090 non-null object 18 Customer Street 23090 non-null object 19 Customer Zipcode 23090 non-null float64 20 Department Id 23090 non-null int64 21 Department Name 23090 non-null object 22 Latitude 23090 non-null object 23 Longitude 23090 non-null object 24 Market 23090 non-null object 25 Order City 23090 non-null object 26 Order Country 23090 non-null object 27 Order Customer Id 23090 non-null int64 28 order date (DateOrders) 23090 non-null object 29 Order Id 23090 non-null int64 30 Order Item Cardprod Id 23090 non-null int64 31 Order Item Discount 23090 non-null object 32 Order Item Discount Rate 23090 non-null float64 33 Order Item Id 23090 non-null int64 34 Order Item Product Price 23090 non-null object 35 Order Item Profit Ratio 23090 non-null object 36 Order Item Quantity 23090 non-null int64 37 Sales 23090 non-null object 38 Order Item Total 23090 non-null object 39 Order Profit Per Order 23090 non-null object 40 Order Region 23090 non-null object 41 Order State 23090 non-null object 42 Order Status 23090 non-null object 43 Order Zipcode 0 non-null float64 44 Product Card Id 23090 non-null int64 45 Product Category Id 23090 non-null int64 46 Product Description 0 non-null float64 47 Product Image 23090 non-null object 48 Product Name 23090 non-null object 49 Product Price 23090 non-null object 50 Product Status 23090 non-null int64 51 shipping date (DateOrders) 23090 non-null object 52 Shipping Mode 23090 non-null object dtypes: float64(6), int64(14), object(33) memory usage: 9.5+ MB
Consideraciones:
1-La informacion general indica que los datos en las columnas del tipo "object", significa que son un cadena de texto u otro tipo no numerico
2-"product description" y "Order Zipcode" esta en blanco toda la columna "Product state" es "0" para toda la columna
Verificar si existen filas duplicadas o espacios vacios.
# verificar filas duplicadas
duplicados=df[df.duplicated()]
if duplicados.empty:
print("No hay filas duplicadas en el DataFrame.")
else:
print("Las siguientes filas están duplicadas:")
print(duplicados)
No hay filas duplicadas en el DataFrame.
# verificar espacios vacios
hay_vacios = df.isna().any().any()
if hay_vacios:
print("El DataFrame contiene valores vacíos.")
else:
print("El DataFrame no contiene valores vacíos.")
El DataFrame contiene valores vacíos.
import pandas as pd
import numpy as np
def check_negative_values(df_1, columns):
"""
Verifica valores negativos en las columnas especificadas del DataFrame,
manejando valores no numéricos y nulos.
Args:
df (pandas.DataFrame): El DataFrame a verificar
columns (list): Lista de nombres de columnas a verificar
Returns:
dict: Un diccionario con los resultados de la verificación
"""
results = {}
for col in columns:
if col not in df_1.columns:
results[col] = f"La columna '{col}' no existe en el DataFrame"
continue
# Convertir la columna a numérica, coerciendo errores a NaN
numeric_col = pd.to_numeric(df_1[col], errors='coerce')
# Contar valores negativos, excluyendo NaN
negative_count = (numeric_col < 0).sum()
nan_count = numeric_col.isna().sum()
if negative_count > 0:
results[col] = f"Se encontraron {negative_count} valores negativos en '{col}'"
else:
results[col] = f"No se encontraron valores negativos en '{col}'"
if nan_count > 0:
results[col] += f". Además, hay {nan_count} valores no numéricos o nulos"
return results
# Uso de la función
columns_to_check = ['Order Item Quantity', 'Sales', 'Order Item Total', 'Product Price']
results = check_negative_values(df_1, columns_to_check)
# Imprimir resultados
for col, result in results.items():
print(result)
# Información adicional sobre tipos de datos
print("\nTipos de datos de las columnas:")
for col in columns_to_check:
if col in df_1.columns:
print(f"{col}: {df_1[col].dtype}")
else:
print(f"{col}: Columna no encontrada")
No se encontraron valores negativos en 'Order Item Quantity' No se encontraron valores negativos en 'Sales'. Además, hay 155013 valores no numéricos o nulos No se encontraron valores negativos en 'Order Item Total'. Además, hay 156939 valores no numéricos o nulos No se encontraron valores negativos en 'Product Price'. Además, hay 155025 valores no numéricos o nulos Tipos de datos de las columnas: Order Item Quantity: int64 Sales: object Order Item Total: object Product Price: object
De acuerdo a la informacion anterior, luego deberemos tratar las columnas precio y ventas
# Cantidad de valores nulos por columna
missing_data = df.isna().sum()
print(missing_data[missing_data > 0])
Order Zipcode 23090 Product Description 23090 dtype: int64
# quitar columnas vacias
df = df.drop(['Product Description', 'Order Zipcode', 'Product Status'], axis=1)
#ELIMINAMOS FILAS DEL DATAFRAME QUE NO USAMOS.
columnas_a_eliminar = ['Sales per customer','Category Id','Customer City','Customer Email','Customer Fname','Customer Lname',
'Customer Password','Customer State','Customer Street','Customer Zipcode','Department Id','Department Name','Latitude',
'Longitude','Market','Order City','Order Customer Id','Order Item Cardprod Id','Order Item Discount', 'Order Item Discount Rate',
'Order Item Profit Ratio','Product Image']
df = df.drop(columns=columnas_a_eliminar)
nombres de columnas
df.columns
Index(['Type', 'Days for shipping (real)', 'Days for shipment (scheduled)', 'Benefit per order', 'Delivery Status', 'Late_delivery_risk', 'Category Name', 'Customer Country', 'Customer Id', 'Customer Segment', 'Order Country', 'order date (DateOrders)', 'Order Id', 'Order Item Id', 'Order Item Product Price', 'Order Item Quantity', 'Sales', 'Order Item Total', 'Order Profit Per Order', 'Order Region', 'Order State', 'Order Status', 'Product Card Id', 'Product Category Id', 'Product Name', 'Product Price', 'shipping date (DateOrders)', 'Shipping Mode'], dtype='object')
#CAMBIAR LAS COLUMNAS A ESPAÑOL
#// prueba para cambiar los valores de las columnas a español
df_espanol=df
#renombro la columna porque tiene espacios
df_espanol.rename(columns={'Category Name':'Categoria',
'Type':'Pago'
,'Days for shipping (real)':'DiasEnvio(Real)'
, 'Days for shipment (scheduled)':'DiasEnvio(Programado)'
, 'Benefit per order':'BeneficioPorPedido'
, 'Delivery Status':'EstadoEntrega'
, 'Late_delivery_risk':'RiesgoEntregaTardia'
, 'Category Name':'Categoria'
, 'Customer Country':'PaisCliente'
, 'Customer Id':'IDCliente'
, 'Customer Segment':'SegmentoCliente'
, 'Order Country':'PaisPedido'
, 'order date (DateOrders)':'FechaPedido'
, 'Order Id':'IDPedido'
, 'Order Item Id':'IDArticuloPedido'
, 'Order Item Product Price':'PrecioArticuloPedido'
, 'Order Item Quantity':'CantidadArticulosPedido'
, 'Sales':'Ventas'
, 'Order Item Total':'TotalArticulosPedido'
, 'Order Profit Per Order':'GananciaPorPedido'
, 'Order Region':'RegionPedido'
, 'Order State':'DestinoPedido'
, 'Order Status':'EstadoPedido'
, 'Product Card Id':'IDProducto'
, 'Product Category Id':'CategoriaProducto'
, 'Product Name':'NombreProducto'
, 'Product Price':'PrecioProducto'
, 'shipping date (DateOrders)':'FechaEnvio'
, 'Shipping Mode':'ModoEnvio'
},inplace=True)
# Columnas traducidas
df_espanol.info()
<class 'pandas.core.frame.DataFrame'> Index: 23090 entries, 84 to 179628 Data columns (total 28 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Pago 23090 non-null object 1 DiasEnvio(Real) 23090 non-null int64 2 DiasEnvio(Programado) 23090 non-null int64 3 BeneficioPorPedido 23090 non-null float64 4 EstadoEntrega 23090 non-null object 5 RiesgoEntregaTardia 23090 non-null int64 6 Categoria 23090 non-null object 7 PaisCliente 23090 non-null object 8 IDCliente 23090 non-null int64 9 SegmentoCliente 23090 non-null object 10 PaisPedido 23090 non-null object 11 FechaPedido 23090 non-null object 12 IDPedido 23090 non-null int64 13 IDArticuloPedido 23090 non-null int64 14 PrecioArticuloPedido 23090 non-null object 15 CantidadArticulosPedido 23090 non-null int64 16 Ventas 23090 non-null object 17 TotalArticulosPedido 23090 non-null object 18 GananciaPorPedido 23090 non-null object 19 RegionPedido 23090 non-null object 20 DestinoPedido 23090 non-null object 21 EstadoPedido 23090 non-null object 22 IDProducto 23090 non-null int64 23 CategoriaProducto 23090 non-null int64 24 NombreProducto 23090 non-null object 25 PrecioProducto 23090 non-null object 26 FechaEnvio 23090 non-null object 27 ModoEnvio 23090 non-null object dtypes: float64(1), int64(9), object(18) memory usage: 5.1+ MB
#tamaño del nuevo dataframe
df.shape
(23090, 28)
Conteo de valores únicos por columna:
df_espanol.nunique()
Pago 4 DiasEnvio(Real) 7 DiasEnvio(Programado) 4 BeneficioPorPedido 8792 EstadoEntrega 4 RiesgoEntregaTardia 2 Categoria 31 PaisCliente 2 IDCliente 5714 SegmentoCliente 3 PaisPedido 3 FechaPedido 7687 IDPedido 7687 IDArticuloPedido 23090 PrecioArticuloPedido 50 CantidadArticulosPedido 5 Ventas 164 TotalArticulosPedido 1575 GananciaPorPedido 8792 RegionPedido 2 DestinoPedido 76 EstadoPedido 9 IDProducto 87 CategoriaProducto 32 NombreProducto 87 PrecioProducto 50 FechaEnvio 7582 ModoEnvio 4 dtype: int64
Verificar si existen filas duplicadas o espacios vacios.
# verificar filas duplicadas
duplicados=df_espanol[df.duplicated()]
if duplicados.empty:
print("No hay filas duplicadas en el DataFrame.")
else:
print("Las siguientes filas están duplicadas:")
print(duplicados)
No hay filas duplicadas en el DataFrame.
# verificar espacios vacios
hay_vacios = df_espanol.isna().any().any()
if hay_vacios:
print("El DataFrame contiene valores vacíos.")
else:
print("El DataFrame no contiene valores vacíos.")
El DataFrame no contiene valores vacíos.
# FIN DE LA PRIMERA PARTE: Exploración Inicial de Datos
# 2 PARTE: ANALISIS UNIVARIADO
Distribución de Variables: Realizar un análisis de las variables individuales para entender su distribución. Utilizar histogramas, boxplots y estadísticas descriptivas (media, mediana, desviación estándar, etc.) para las variables numéricas. Para las variables categóricas, calcular frecuencias y proporciones.
Identificación de Outliers: Detectar posibles outliers en las variables numéricas utilizando técnicas como el análisis de boxplots o el cálculo del z-score.
# VER LOS VALORES DE UNA VARIABLE
df_espanol.Categoria.unique()
array(["Women's Apparel", 'Shop By Sport', 'Electronics',
'Baseball & Softball', 'Cardio Equipment', 'Boxing & MMA',
'Cleats', "Girls' Apparel", 'Accessories', 'Golf Balls',
'Trade-In', 'Hockey', 'Camping & Hiking', 'Fishing',
"Men's Footwear", 'Soccer', 'Fitness Accessories',
"Kids' Golf Clubs", 'Tennis & Racquet', 'Lacrosse',
'Hunting & Shooting', 'As Seen on TV!', 'Strength Training',
'Golf Gloves', 'Golf Bags & Carts', 'Golf Shoes', 'Golf Apparel',
"Women's Golf Clubs", "Men's Golf Clubs", 'Water Sports',
'Indoor/Outdoor Games'], dtype=object)
Valores de Pago
df_espanol.Pago.unique()
array(['PAYMENT', 'TRANSFER', 'DEBIT', 'CASH'], dtype=object)
Valores de Modo de Envio
df_espanol.ModoEnvio.unique()
array(['Second Class', 'Standard Class', 'First Class', 'Same Day'],
dtype=object)
Valores de Segmento de Clientes
df_espanol.SegmentoCliente.unique()
array(['Home Office', 'Consumer', 'Corporate'], dtype=object)
Valores de Estado de Entrega
df_espanol.EstadoEntrega.unique()
array(['Late delivery', 'Shipping on time', 'Advance shipping',
'Shipping canceled'], dtype=object)
#EXPLORAMOS LOS DATOS:
#Obtenemos estadísticas descriptivas sobre las columnas numéricas del conjunto de datos:
df_espanol.describe()
| DiasEnvio(Real) | DiasEnvio(Programado) | BeneficioPorPedido | RiesgoEntregaTardia | IDCliente | IDPedido | IDArticuloPedido | CantidadArticulosPedido | IDProducto | CategoriaProducto | |
|---|---|---|---|---|---|---|---|---|---|---|
| count | 23090.000000 | 23090.000000 | 2.309000e+04 | 23090.000000 | 23090.000000 | 23090.000000 | 23090.000000 | 23090.000000 | 23090.000000 | 23090.000000 |
| mean | 3.532395 | 2.957687 | 2.337699e+09 | 0.544651 | 6239.185881 | 31248.316544 | 78148.127934 | 2.182763 | 664.433911 | 30.279385 |
| std | 1.628313 | 1.354260 | 3.819456e+09 | 0.498013 | 3574.207795 | 25789.096724 | 64514.324265 | 1.471115 | 309.893562 | 13.687618 |
| min | 0.000000 | 0.000000 | -9.984000e+09 | 0.000000 | 3.000000 | 1.000000 | 1.000000 | 1.000000 | 19.000000 | 2.000000 |
| 25% | 2.000000 | 2.000000 | 7.050000e+01 | 0.000000 | 3184.000000 | 5498.000000 | 13714.250000 | 1.000000 | 403.000000 | 18.000000 |
| 50% | 3.000000 | 4.000000 | 1.966500e+09 | 1.000000 | 6194.000000 | 51386.000000 | 128407.500000 | 1.000000 | 627.000000 | 29.000000 |
| 75% | 5.000000 | 4.000000 | 4.963000e+09 | 1.000000 | 9299.500000 | 56713.750000 | 141840.750000 | 3.000000 | 1004.000000 | 45.000000 |
| max | 6.000000 | 4.000000 | 9.999000e+09 | 1.000000 | 12434.000000 | 61584.000000 | 153996.000000 | 5.000000 | 1073.000000 | 48.000000 |
# Para cada COLUMNA NUMERICA DE INTERES calcular la mediana, MEDIA Y DESVIACION ESTANDAR
# EJEMPLO PARA Benefit per order Y PRECIO DE PRODUCTO
# el precio del producto tiene valores vacios...ademas hay que convertirlo porque esta en formato Object..a numerico para hacer calculos
import re
import pandas as pd
def clean_price(price_str):
if pd.isna(price_str):
return None
# Convertir a string si no lo es
price_str = str(price_str)
# Eliminar espacios en blanco y caracteres no numéricos excepto punto y coma
cleaned = re.sub(r'[^\d.,]', '', price_str)
# Reemplazar coma por punto si hay más de un punto (asumiendo que la coma es el separador decimal)
if cleaned.count('.') > 1 and ',' in cleaned:
cleaned = cleaned.replace(',', '.')
# Si hay más de un punto, asumimos que todos menos el último son separadores de miles
parts = cleaned.split('.')
if len(parts) > 2:
integer_part = ''.join(parts[:-1])
decimal_part = parts[-1]
cleaned = f"{integer_part}.{decimal_part}"
try:
return float(cleaned)
except ValueError:
print(f"No se pudo convertir: {price_str}")
return None
# Aplicar la función a la columna 'Product Price' y mostrar los resultados
df_espanol['Clean Price'] = df['PrecioProducto'].apply(clean_price)
# Mostrar filas donde la limpieza falló
failed_conversions = df[df['PrecioProducto'].isna()]
print("Filas donde la conversión falló:")
print(failed_conversions[['PrecioProducto', 'Clean Price']])
# Calcular la mediana de los precios limpios
median_prices = df.groupby('Categoria')['Clean Price'].median()
print("\nMediana de precios de productos segun categoria:")
print(median_prices)
# Calcular la media de los precios limpios
media_prices = df.groupby('Categoria')['Clean Price'].mean()
print("\nMedia de precios de productos segun categoria:")
print(media_prices)
# Calcular la desviacion estandar de los precios limpios
std_prices = df.groupby('Categoria')['Clean Price'].std()
print("\nDesviacion estandar de productos segun categoria:")
print(std_prices)
# Mostrar estadísticas de la columna de precios limpios
print("\nEstadísticas de la columna de precio de productos:")
print(df['Clean Price'].describe())
Filas donde la conversión falló: Empty DataFrame Columns: [PrecioProducto, Clean Price] Index: [] Mediana de precios de productos segun categoria: Categoria Accessories 2498999.977 As Seen on TV! 9998999.786 Baseball & Softball 3499000.168 Boxing & MMA 8998999.786 Camping & Hiking 299980.011 Cardio Equipment 9998999.786 Cleats 5999000.168 Electronics 3198999.977 Fishing 399980.011 Fitness Accessories 3499000.168 Girls' Apparel 70.000 Golf Apparel 1998999.977 Golf Bags & Carts 1699900.055 Golf Balls 1798999.977 Golf Gloves 3999000.168 Golf Shoes 80.000 Hockey 22.000 Hunting & Shooting 2998999.977 Indoor/Outdoor Games 4997999.954 Kids' Golf Clubs 1999900.055 Lacrosse 2498999.977 Men's Footwear 1299900.055 Men's Golf Clubs 1324900.055 Shop By Sport 3999000.168 Soccer 7998999.786 Strength Training 189.000 Tennis & Racquet 4499000.168 Trade-In 1598999.977 Water Sports 1999900.055 Women's Apparel 50.000 Women's Golf Clubs 7998999.786 Name: Clean Price, dtype: float64 Media de precios de productos segun categoria: Categoria Accessories 2.499000e+06 As Seen on TV! 9.999000e+06 Baseball & Softball 4.362567e+06 Boxing & MMA 7.405708e+06 Camping & Hiking 2.999800e+05 Cardio Equipment 9.753777e+06 Cleats 5.999000e+06 Electronics 3.986990e+06 Fishing 3.999800e+05 Fitness Accessories 3.499000e+06 Girls' Apparel 1.312678e+06 Golf Apparel 1.721369e+06 Golf Bags & Carts 1.699900e+06 Golf Balls 1.774500e+06 Golf Gloves 5.901723e+06 Golf Shoes 8.122826e+01 Hockey 2.342308e+01 Hunting & Shooting 2.346087e+06 Indoor/Outdoor Games 4.998000e+06 Kids' Golf Clubs 5.153402e+06 Lacrosse 4.604263e+06 Men's Footwear 1.299900e+06 Men's Golf Clubs 2.857235e+06 Shop By Sport 3.879653e+06 Soccer 5.839288e+06 Strength Training 1.890000e+02 Tennis & Racquet 4.499000e+06 Trade-In 1.899081e+06 Water Sports 1.999900e+06 Women's Apparel 5.000000e+01 Women's Golf Clubs 6.459881e+06 Name: Clean Price, dtype: float64 Desviacion estandar de productos segun categoria: Categoria Accessories 0.000000e+00 As Seen on TV! 0.000000e+00 Baseball & Softball 1.615250e+06 Boxing & MMA 1.902672e+06 Camping & Hiking 0.000000e+00 Cardio Equipment 1.547033e+06 Cleats 0.000000e+00 Electronics 9.034617e+05 Fishing 0.000000e+00 Fitness Accessories 0.000000e+00 Girls' Apparel 1.885016e+06 Golf Apparel 3.644281e+05 Golf Bags & Carts 0.000000e+00 Golf Balls 2.190655e+05 Golf Gloves 3.338846e+06 Golf Shoes 1.795299e+01 Hockey 1.507722e+00 Hunting & Shooting 1.038113e+06 Indoor/Outdoor Games 0.000000e+00 Kids' Golf Clubs 4.335915e+06 Lacrosse 3.400022e+06 Men's Footwear 0.000000e+00 Men's Golf Clubs 3.413800e+06 Shop By Sport 6.421471e+05 Soccer 3.213214e+06 Strength Training 0.000000e+00 Tennis & Racquet 0.000000e+00 Trade-In 3.393157e+05 Water Sports 0.000000e+00 Women's Apparel 0.000000e+00 Women's Golf Clubs 3.646446e+06 Name: Clean Price, dtype: float64 Estadísticas de la columna de precio de productos: count 2.309000e+04 mean 3.035057e+06 std 2.934299e+06 min 2.200000e+01 25% 3.999800e+05 50% 1.999900e+06 75% 4.998000e+06 max 9.999000e+06 Name: Clean Price, dtype: float64
import re
import pandas as pd
def clean_Beneficio_por_pedido(benPP_str):
if pd.isna(benPP_str):
return None
# Convertir a string si no lo es
benPP_str = str(benPP_str)
# Eliminar espacios en blanco y caracteres no numéricos excepto punto y coma
cleaned = re.sub(r'[^\d.,]', '', benPP_str)
# Reemplazar coma por punto si hay más de un punto (asumiendo que la coma es el separador decimal)
if cleaned.count('.') > 1 and ',' in cleaned:
cleaned = cleaned.replace(',', '.')
# Si hay más de un punto, asumimos que todos menos el último son separadores de miles
parts = cleaned.split('.')
if len(parts) > 2:
integer_part = ''.join(parts[:-1])
decimal_part = parts[-1]
cleaned = f"{integer_part}.{decimal_part}"
try:
return float(cleaned)
except ValueError:
print(f"No se pudo convertir: {benPP_str}")
return None
# Aplicar la función a la columna 'Benefit per order' y mostrar los resultados
df['clean_Beneficio_por_pedido'] = df['BeneficioPorPedido'].apply(clean_Beneficio_por_pedido)
# Mostrar filas donde la limpieza falló
failed_conversions = df[df['clean_Beneficio_por_pedido'].isna()]
print("Filas donde la conversión falló:")
print(failed_conversions[['BeneficioPorPedido', 'clean_Beneficio_por_pedido']])
# Calcular la mediana -Beneficio por orden limpio
median_prices = df.groupby('IDPedido')['clean_Beneficio_por_pedido'].median()
print("\nMediana de precios por producto:")
print(median_prices)
# Calcular la media -Beneficio por orden limpio
media_prices = df.groupby('IDPedido')['clean_Beneficio_por_pedido'].mean()
print("\nMedia de precios de productos segun categoria:")
print(media_prices)
# Calcular la desviacion estandar -Beneficio por orden limpio
std_prices = df.groupby('IDPedido')['clean_Beneficio_por_pedido'].std()
print("\nDesviacion estandar de productos segun categoria:")
print(std_prices)
# Mostrar estadísticas de la columna de precios limpios
print("\nEstadísticas de la columna Beneficio por Pedido:")
print(df['clean_Beneficio_por_pedido'].describe())
Filas donde la conversión falló:
Empty DataFrame
Columns: [BeneficioPorPedido, clean_Beneficio_por_pedido]
Index: []
Mediana de precios por producto:
IDPedido
1 8.879000e+09
7 4.580000e+09
8 1.499750e+09
9 1.980000e+09
10 1.564000e+09
...
61580 1.161900e+09
61581 5.390000e+09
61582 1.050000e+09
61583 2.910000e+09
61584 2.291000e+09
Name: clean_Beneficio_por_pedido, Length: 7687, dtype: float64
Media de precios de productos segun categoria:
IDPedido
1 8.879000e+09
7 4.543167e+09
8 2.614875e+09
9 1.926667e+09
10 1.622400e+09
...
61580 2.498520e+09
61581 5.390000e+09
61582 9.414667e+08
61583 3.126233e+09
61584 2.846750e+09
Name: clean_Beneficio_por_pedido, Length: 7687, dtype: float64
Desviacion estandar de productos segun categoria:
IDPedido
1 NaN
7 3.315404e+09
8 3.198542e+09
9 1.900561e+09
10 1.079475e+09
...
61580 3.619780e+09
61581 5.232589e+08
61582 8.921650e+08
61583 1.335544e+09
61584 3.036507e+09
Name: clean_Beneficio_por_pedido, Length: 7687, dtype: float64
Estadísticas de la columna Beneficio por Pedido:
count 2.309000e+04
mean 3.543691e+09
std 2.737705e+09
min 0.000000e+00
25% 1.329900e+09
50% 2.886000e+09
75% 5.481000e+09
max 9.999000e+09
Name: clean_Beneficio_por_pedido, dtype: float64
#histogramas, boxplots -valores atipicos
def create_boxplots_and_percentiles(df, columns):
# Verificar si las columnas existen en el DataFrame
for col in columns:
if col not in df_espanol.columns:
raise ValueError(f"La columna '{col}' no existe en el DataFrame")
# Crear subplots
fig = make_subplots(rows=len(columns), cols=1,
subplot_titles=[f'Boxplot de {col}' for col in columns],
vertical_spacing=0.1)
# Crear un boxplot para cada columna especificada
for i, col in enumerate(columns, 1):
fig.add_trace(
go.Box(y=df_espanol[col], name=col, boxpoints='outliers'),
row=i, col=1
)
# Actualizar el diseño
fig.update_layout(height=300*len(columns), width=800, showlegend=False,
title_text="Boxplots de ventas y precio")
# Mostrar el gráfico
fig.show()
# Calcular y mostrar percentiles
print("Percentiles para ventas y precio:")
for col in columns:
percentiles = df_espanol[col].describe(percentiles=[.01, .25, .5, .75, .99])
print(f"\n{col}:")
print(percentiles)
# Usar la función
columns_to_analyze = ["DiasEnvio(Real)","DiasEnvio(Programado)","Ventas", "PrecioProducto","BeneficioPorPedido","CantidadArticulosPedido"]
try:
create_boxplots_and_percentiles(df, columns_to_analyze)
except ValueError as e:
print(f"Error: {e}")
print("Columnas disponibles en el DataFrame:")
print(df.columns.tolist())
Percentiles para ventas y precio: DiasEnvio(Real): count 23090.000000 mean 3.532395 std 1.628313 min 0.000000 1% 0.000000 25% 2.000000 50% 3.000000 75% 5.000000 99% 6.000000 max 6.000000 Name: DiasEnvio(Real), dtype: float64 DiasEnvio(Programado): count 23090.000000 mean 2.957687 std 1.354260 min 0.000000 1% 0.000000 25% 2.000000 50% 4.000000 75% 4.000000 99% 4.000000 max 4.000000 Name: DiasEnvio(Programado), dtype: float64 Ventas: count 23090 unique 164 top 1.299.900.055 freq 2992 Name: Ventas, dtype: object PrecioProducto: count 23090 unique 50 top 5.999.000.168 freq 3251 Name: PrecioProducto, dtype: object BeneficioPorPedido: count 2.309000e+04 mean 2.337699e+09 std 3.819456e+09 min -9.984000e+09 1% -8.645760e+09 25% 7.050000e+01 50% 1.966500e+09 75% 4.963000e+09 99% 9.730000e+09 max 9.999000e+09 Name: BeneficioPorPedido, dtype: float64 CantidadArticulosPedido: count 23090.000000 mean 2.182763 std 1.471115 min 1.000000 1% 1.000000 25% 1.000000 50% 1.000000 75% 3.000000 99% 5.000000 max 5.000000 Name: CantidadArticulosPedido, dtype: float64
#Numero de pedidos y tiempo de entrega real
dias_entrega_real=df_espanol.groupby(['DiasEnvio(Real)'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='DiasEnvio(Real)', y='Numero de Pedidos' , color='DiasEnvio(Real)',
)
fig.show()
##Numero de pedidos y tiempo de entrega programado
dias_entrega_real=df_espanol.groupby(['DiasEnvio(Programado)'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='DiasEnvio(Programado)', y='Numero de Pedidos' , color='DiasEnvio(Programado)'
)
fig.show()
#Frecuencia de productos
dias_entrega_real=df_espanol.groupby(['NombreProducto'])['IDProducto'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='NombreProducto', y='Numero de Pedidos' , color='NombreProducto'
)
fig.show()
#Cantidad de pedidos segun categoria
dias_entrega_real=df_espanol.groupby(['Categoria'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='Categoria', y='Numero de Pedidos' , color='Categoria'
)
fig.show()
#Cantidad de productos segun categoria
dias_entrega_real=df_espanol.groupby(['Categoria'])['IDProducto'].count().reset_index(name='cantidad de productos').sort_values(by= 'cantidad de productos', ascending= False)
fig=px.bar(dias_entrega_real, x='Categoria', y='cantidad de productos' , color='Categoria'
)
fig.show()
# Ventas segun categoria de producto
# Aplicar la función anterior para formatear la columna 'Ventas' y mostrar los resultados
df_espanol['Ventas'] = df_espanol['Ventas'].apply(clean_Beneficio_por_pedido)
#dividimos el valor para poder graficar
df_espanol['Ventas1'] = df_espanol['Ventas']/100000
#Graficar
dias_entrega_real=df_espanol.groupby(['Categoria'])['Ventas1'].sum().reset_index(name='Total ventas').sort_values(by= 'Total ventas', ascending= False)
fig=px.bar(dias_entrega_real, x='Categoria', y='Total ventas' , color='Categoria'
)
fig.show()
##estado de las ordenes (segun pais) - se discrimina por el estado de la orden
data_delivery_status_region=df_espanol.groupby(['EstadoPedido', 'PaisPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoPedido', y='Number of Orders' , color='PaisPedido',
)
fig.show()
#estado de las ordenes segun region - discriminado por estado de las ordenes
data_delivery_status_region=df_espanol.groupby(['EstadoPedido', 'RegionPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoPedido', y='Number of Orders' , color='RegionPedido',
)
fig.show()
#Estado de pedido segun el pais cliente
data_delivery_status_region=df_espanol.groupby(['EstadoPedido', 'PaisCliente'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoPedido', y='Number of Orders' , color='PaisCliente',
)
fig.show()
#Estado de envios segun el pais
data_delivery_status_region=df_espanol.groupby(['EstadoEntrega', 'PaisPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoEntrega', y='Number of Orders' , color='PaisPedido',
)
fig.show()
#Estado de envios segun region
data_delivery_status_region=df_espanol.groupby(['EstadoEntrega', 'RegionPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoEntrega', y='Number of Orders' , color='RegionPedido',
)
fig.show()
Analisis solo para argentina*
# Primero, filtramos el DataFrame para incluir solo los datos de Argentina
df_argentina = df_espanol[df_espanol['PaisPedido'] == 'Argentina']
# Ahora realizamos el agrupamiento solo con los datos de Argentina
data_delivery_status_argentina = df_argentina.groupby('EstadoEntrega')['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by='Numero de Pedidos', ascending=False)
# Creamos el gráfico de barras
fig = px.bar(data_delivery_status_argentina,
x='EstadoEntrega',
y='Numero de Pedidos',
title='Estado de Entrega de Pedidos para Argentina')
# Mostramos el gráfico
fig.show()
#solo para el pais cliente Puerto Rico
# Primero, filtramos el DataFrame para incluir solo los datos de Argentina
df_argentina = df_espanol[df_espanol['PaisCliente'] == 'Puerto Rico']
# Ahora realizamos el agrupamiento solo con los datos de Argentina
data_delivery_status_argentina = df_argentina.groupby('EstadoEntrega')['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by='Numero de Pedidos', ascending=False)
# Creamos el gráfico de barras
fig = px.bar(data_delivery_status_argentina,
x='EstadoEntrega',
y='Numero de Pedidos',
title='Estado de los pedidos que iran a Puerto Rico')
# Mostramos el gráfico
fig.show()
#segun la cantidad de pedidos
df_espanol['Customer_ID_STR']=df_espanol['IDCliente'].astype(str)
data_customers=df_espanol.groupby(['Customer_ID_STR'])['IDCliente'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(data_customers.head(20),x='Numero de Pedidos', y='Customer_ID_STR' , color='Numero de Pedidos' )
fig.show()
#segun la cantidad de pedidos de argentina
# Primero, filtramos el DataFrame para incluir solo los datos de Argentina
df_argentina = df_espanol[df_espanol['PaisPedido'] == 'Argentina']
data_customers=df_argentina.groupby(['Customer_ID_STR'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(data_customers.head(20),x='Numero de Pedidos', y='Customer_ID_STR' , color='Numero de Pedidos' )
fig.show()
#20 principales clientes segun las ganancias de todos los pedidos
df_espanol['Customer_ID_STR']=df_espanol['IDCliente'].astype(str)
data_customers_profit=df_espanol.groupby(['Customer_ID_STR'])['Ventas1'].sum().reset_index(name='Ventas1').sort_values(by= 'Ventas1', ascending= False)
fig=px.bar(data_customers_profit.head(20),x='Ventas1', y='Customer_ID_STR' , color='Ventas1' )
fig.show()
#LOS VALORES ESTAN DIVIDIDOS POR MILLONES
#Cantidad de pedidos segun el segmento de clientes
data_Customer_Segment=df_espanol.groupby(['SegmentoCliente'])['IDCliente'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.pie(data_Customer_Segment, values='Numero de Pedidos', names= 'SegmentoCliente' , title= 'Numbero de pedidos segun segmento de cliente',
width=600 , height=600 , color_discrete_sequence = px.colors.qualitative.D3)
fig.show()
#Segmento de Clientes para la region de America del sur
df_argentina = df_espanol[df_espanol['RegionPedido'] == 'South America']
data_Customer_Segment=df_argentina.groupby(['SegmentoCliente'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
px.pie(data_Customer_Segment, values='Numero de Pedidos', names= 'SegmentoCliente' , title= 'Numbero de pedidos segun segmento de cliente',
width=600 , height=600 , color_discrete_sequence = ["red", "green", "blue", "goldenrod", "magenta"])
#Customer Segments de cordoba
df_argentina = df_espanol[df_espanol['RegionPedido'] == 'Central America']
data_Customer_Segment=df_argentina.groupby(['SegmentoCliente'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
px.pie(data_Customer_Segment, values='Numero de Pedidos', names= 'SegmentoCliente' , title= 'Numbero de pedidos segun segmento de cliente',
width=600 , height=600 , color_discrete_sequence = px.colors.qualitative.G10)
#Categorias
data_Category_Name=df_espanol.groupby(['Categoria'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_Category_Name, x='Numero de Pedidos',y = 'Categoria',color ='Numero de Pedidos')
# categorias para argentina
df_argentina = df_espanol[df_espanol['PaisPedido'] == 'Argentina']
data_Category_Name=df_argentina.groupby(['Categoria'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_Category_Name, x='Numero de Pedidos',y = 'Categoria',color ='Numero de Pedidos')
#Segun region
data_Region=df_espanol.groupby(['RegionPedido'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_Region, x='Numero de Pedidos',y = 'RegionPedido',color ='Numero de Pedidos')
# segun el pais de pedido
data_countries=df_espanol.groupby(['PaisPedido'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_countries.head(20), x='Numero de Pedidos',y = 'PaisPedido',color ='Numero de Pedidos')
#total de ventas por pais
data_countries=df_espanol.groupby(['PaisPedido'])['Ventas1'].sum().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_countries.head(20), x='Numero de Pedidos',y = 'PaisPedido',color ='Numero de Pedidos')
df_geo=df_espanol.groupby([ 'RegionPedido', 'PaisPedido'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
df_geo
| RegionPedido | PaisPedido | Ventas | |
|---|---|---|---|
| 0 | Central America | Mexico | 282077.461240 |
| 2 | South America | Brasil | 170193.677838 |
| 1 | South America | Argentina | 41405.607661 |
import pandas as pd
import plotly.express as px
# Asumiendo que ya tienes tu DataFrame 'df_geo'
# Crear el gráfico de coropletas
fig = px.choropleth(df_geo,
locationmode='country names',
locations='PaisPedido',
color='Ventas',
hover_name='PaisPedido',
color_continuous_scale=px.colors.sequential.Plasma)
# Ajustar el diseño para una mejor visualización
fig.update_layout(
title_text='Mapa de Ventas por País',
geo=dict(
showframe=False,
showcoastlines=True,
projection_type='equirectangular'
)
)
# Mostrar el gráfico
fig.show()
df_espanol.PaisPedido.unique()
array(['Brasil', 'Mexico', 'Argentina'], dtype=object)
# Ventas por pais en grafico circular
df_geo=df_espanol.groupby([ 'RegionPedido', 'PaisPedido'])['Ventas1'].sum().reset_index(name='Ventas1').sort_values(by= 'Ventas1', ascending= False)
px.pie(df_geo, values='Ventas1', names= 'PaisPedido' , title= 'Number de pedidos por pais',
width=600 , height=600 , color_discrete_sequence = px.colors.qualitative.G10)
# ventas por region
df_sales_country=df_espanol.groupby([ 'RegionPedido'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
px.bar(df_sales_country.head(10), x='Ventas de pedido',y = 'RegionPedido',color ='Ventas de pedido')
#Cantidad de ventas por pais de pedido
df_sales_country=df_espanol.groupby([ 'PaisPedido'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
fig=px.bar(df_sales_country.head(10), x='Ventas de pedido',y = 'PaisPedido',color ='Ventas de pedido')
fig.show()
#Ventas por producto
df_sales_country=df_espanol.groupby([ 'NombreProducto'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
fig=px.bar(df_sales_country.head(10), x='Ventas de pedido',y = 'NombreProducto',color ='Ventas de pedido')
fig.show()
#Productos, estado de entrega y ventas
df_sales_pd=df_espanol.groupby([ 'NombreProducto', 'EstadoEntrega'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
px.bar(df_sales_pd.head(10), x='Ventas de pedido',y = 'NombreProducto',color ='EstadoEntrega')
#Productos por region y ventas
df_sales_pr=df_espanol.groupby([ 'NombreProducto', 'RegionPedido'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
fig=px.bar(df_sales_pr.head(10), x='Ventas de pedido',y = 'NombreProducto',color ='RegionPedido')
fig.show()
#Ventas por Categoria
df_sales_pr=df_espanol.groupby([ 'Categoria'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
px.bar(df_sales_pr.head(10), x='Ventas',y = 'Categoria',color ='Categoria')
#Segun el tipo de pago
df_sales_pr=df_espanol.groupby([ 'Pago'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
px.bar(df_sales_pr.head(10), x='Ventas',y = 'Pago',color ='Ventas')
#Productos, pagos y ventas
df_sales_tp=df_espanol.groupby([ 'NombreProducto','Pago'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_tp.head(100), x='Ventas',y = 'Pago',color ='NombreProducto')
fig.show()
import datetime as dt
data_orderdate=df_espanol[['FechaEnvio', 'Ventas1']]
data_orderdate['order_date'] = pd.to_datetime(data_orderdate['FechaEnvio'])
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\1666086263.py:4: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
data_orderdate["Quarter"] = data_orderdate['order_date'].dt.quarter
data_orderdate["Month"] = data_orderdate['order_date'].dt.month
data_orderdate["year"] = data_orderdate['order_date'].dt.year
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:2: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:3: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
data_orderdate["Quarter"] = data_orderdate['order_date'].dt.quarter
data_orderdate["Month"] = data_orderdate['order_date'].dt.month
data_orderdate["year"] = data_orderdate['order_date'].dt.year
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:2: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:3: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
data_orderdate['YearStr']=data_orderdate['year'].astype(str)
df_sales_year=data_orderdate.groupby([ 'YearStr'])['Ventas1'].sum().reset_index(name='Ventas de Pedido').sort_values(by= 'Ventas de Pedido', ascending= False)
fig=px.bar(df_sales_year, x='Ventas de Pedido',y = 'YearStr',color ='Ventas de Pedido')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\712514235.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
data_orderdate['QuarterStr']=data_orderdate['Quarter'].astype(str)
df_sales_quarter=data_orderdate.groupby([ 'YearStr','QuarterStr'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_quarter, x='Ventas',y = 'QuarterStr',color ='YearStr')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\695585461.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
data_orderdate['MonthStr']=data_orderdate['Month'].astype(str)
df_sales_m=data_orderdate.groupby([ 'QuarterStr', 'MonthStr'])['Ventas1'].sum().reset_index(name='Ventas1').sort_values(by= 'Ventas1', ascending= False)
fig=px.bar(df_sales_m, x='Ventas1',y = 'QuarterStr',color ='MonthStr')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\1003044912.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
data_orderdate['YearStr']=data_orderdate['Month'].astype(str)
df_sales_quarter=data_orderdate.groupby([ 'YearStr','Month'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_quarter, x='YearStr',y = 'Ventas',color ='Month')
fig.show()
# ver detalle YearStr
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\2979100799.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
data_orderdate['YearStr'].unique()
array(['4', '3', '2', '1', '5', '6'], dtype=object)
#separar la fecha
df_espanol1=df_espanol
# Primero, convertimos la columna a tipo datetime
df_espanol1['FechaEnvio'] = pd.to_datetime(df_espanol1['FechaEnvio'])
# Ahora creamos las nuevas columnas
df_espanol1['dia'] = df_espanol1['FechaEnvio'].dt.day
df_espanol1['mes'] = df_espanol1['FechaEnvio'].dt.month
df_espanol1['anio'] = df_espanol1['FechaEnvio'].dt.year
# Si quieres que el formato sea exactamente como 1-18-2018, puedes hacer:
df_espanol1['fecha_formateada'] = df_espanol1['FechaEnvio'].dt.strftime('%d-%m-%Y')
data_orderdate['YearStr']=data_orderdate['Month'].astype(str)
df_sales_quarter=df_espanol1.groupby([ 'anio','mes'])['Ventas1'].count().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_quarter, x='anio',y = 'Ventas',color ='Ventas')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3745632177.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
import pandas as pd
import plotly.graph_objects as go
# 'tendencias'
# y tiene las columnas 'PaisPedido', 'anio', y 'IDPedido'
# Calcular la producción total por año y Provincia
tendencias = df_espanol.groupby(['PaisPedido','anio'])['IDPedido'].count().reset_index()
# Crear una figura
fig = go.Figure()
# Iterar a través de países únicos
for pais in tendencias['PaisPedido'].unique():
# Filtrar datos para el país actual
data_pais = tendencias[tendencias['PaisPedido'] == pais]
# Agregar una línea para cada país
fig.add_trace(go.Scatter(
x=data_pais['anio'],
y=data_pais['IDPedido'],
mode='lines',
name=pais
))
# Personalizar el diseño del gráfico
fig.update_layout(
title='Tendencias en pedidos por Años',
xaxis_title='Año',
yaxis_title='Cantidad de Pedidos',
legend_title_text='País',
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
)
)
# Agregar líneas de cuadrícula
fig.update_xaxes(showgrid=True)
fig.update_yaxes(showgrid=True)
# Mostrar el gráfico
fig.show()
df_espanol['PrecioProducto'] = df_espanol['PrecioProducto'].apply(clean_Beneficio_por_pedido)
df_espanol['Precio2'] = df_espanol['PrecioProducto']/1000
#CANTIDAD DE PEDIDOS POR AÑO SEGUN EL PRODUCTO
import pandas as pd
import plotly.graph_objects as go
# Calcular region, año
tendencias = df_espanol.groupby(['RegionPedido','anio'])['IDPedido'].count().reset_index()
# 'tendencias'
# y tiene las columnas 'PaisRegion', 'anio', y 'IDPedido'
# Crear una figura
fig = go.Figure()
# Iterar a través de países únicos
for pais in tendencias['RegionPedido'].unique():
# Filtrar datos para el país actual
data_pais = tendencias[tendencias['RegionPedido'] == pais]
# Agregar una línea para cada país
fig.add_trace(go.Scatter(
x=data_pais['anio'],
y=data_pais['IDPedido'],
mode='lines',
name=pais
))
# Personalizar el diseño del gráfico
fig.update_layout(
title='Tendencias en pedidos por Años',
xaxis_title='Año',
yaxis_title='Cantidad de Pedidos',
legend_title_text='País',
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
)
)
# Agregar líneas de cuadrícula
fig.update_xaxes(showgrid=True)
fig.update_yaxes(showgrid=True)
# Mostrar el gráfico
fig.show()
import pandas as pd
import plotly.graph_objects as go
# Asumiendo que tu DataFrame se llama 'tendencias'
# y tiene las columnas 'Producto', 'anio', y 'IDPedido'
tendencias = df_espanol.groupby(['NombreProducto','anio'])['IDPedido'].count().reset_index()
# Crear una figura
fig = go.Figure()
# Iterar a través de países únicos
for pais in tendencias['NombreProducto'].unique():
# Filtrar datos para el país actual
data_pais = tendencias[tendencias['NombreProducto'] == pais]
# Agregar una línea para cada país
fig.add_trace(go.Scatter(
x=data_pais['anio'],
y=data_pais['IDPedido'],
mode='lines',
name=pais
))
# Personalizar el diseño del gráfico
fig.update_layout(
title='Tendencias en pedidos por Años',
xaxis_title='Año',
yaxis_title='Cantidad de Pedidos',
legend_title_text='País',
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
)
)
# Agregar líneas de cuadrícula
fig.update_xaxes(showgrid=True)
fig.update_yaxes(showgrid=True)
# Mostrar el gráfico
fig.show()
# Excluir columnas no numéricas
numeric_df_espanol = df_espanol.select_dtypes(include=[np.number])
# Crear el mapa de calor de correlación
plt.figure(figsize=(16, 6))
heatmap = sns.heatmap(numeric_df_espanol.corr(), annot=True, cmap='BrBG')
heatmap.set_title('Mapa de calor de correlación', fontdict={'fontsize': 18}, pad=12)
plt.show()
# Elegir las dos columnas numéricas que deseas comparar
columna_x = 'PrecioProducto'
columna_y = 'Ventas1'
# Crear el gráfico de dispersión
plt.figure(figsize=(10, 6))
plt.scatter(df_espanol[columna_x], df_espanol[columna_y], alpha=0.5, color='blue')
plt.title(f'Gráfico de Dispersión entre {columna_x} y {columna_y}')
plt.xlabel(columna_x)
plt.ylabel(columna_y)
plt.grid(True)
plt.show()